#include "TCPBasic.hpp"
#include <stdio.h>

#define K 1024
#define M (1024*1024)

typedef struct _TCP_PACKET
{
	char buf[8*K];
	int packetSize;
	int netIdx;				// other message

	inline int maxBufSize(){return 8*K;}
	inline int& size(){return packetSize;};
	inline char* operator*(){return buf;}
	inline int& getIdx(){return netIdx;}
} TCP_PACKET, *LPTCP_PACKET;

typedef struct _NETBUF
{
	int idx;
	int packetSize;
	char buf[8*K-2*sizeof(int)];
	inline _NETBUF(){memset(this, 0, sizeof(struct _NETBUF));};
}NETBUF, *PNETBUF;

void TCP_Server(int port, int nTimes)
{
	printf("server\n");

	CTCPBasic<TCP_PACKET> *pServer = new CTCPServer<TCP_PACKET>(port);
	PNETBUF pBuf = new NETBUF;
	CTimeSpeed timeSpeed;
	float speed;

	pServer->BeforeNetworking();

	int nTimer = 0;
	while(nTimes--)
	{
		nTimer = 100*M / (8*K);
		timeSpeed.SetMark();
		while(nTimer --)
		{	
			pServer->nRecvLen = pServer->Receive();
			if(pServer->nRecvLen < 0) break;
			if(pServer->nRecvLen == 0) {nTimer++; continue;} 
			
			memcpy(pBuf, pServer->GetPacketPtr(), pServer->nRecvLen);
			pBuf->packetSize = pServer->nRecvLen;
			
			if(nTimer % (10*M/(8*K)) == 0)
				printf("recv : %d%%\n", 10 - nTimer / (10*M/(8*K)));
		#if RECV_AND_SEND	
			pServer->nSendLen = pServer->Send();
		#endif
		}
		if(nTimer > 0)
		{
			printf("recv error\n");
			break;
		}
		speed =  100 / timeSpeed.GetSpeed();
		printf("\n%d Receive from port: %d %d Mbyte complete, speed : %fM/S\n", pBuf->idx, port, 100, speed);
	}
	delete pBuf;
	delete pServer;
}

void TCP_Client(char *ip, int port, int nTimes)
{
	printf("client\n");

	CTCPBasic<TCP_PACKET> *pClient = new CTCPClient<TCP_PACKET>(ip, port);
	PNETBUF pBuf = new NETBUF;
	
	CTimeSpeed timeSpeed;
	float speed;

	if(pClient->Create() != TRUE || ((CTCPBasic<TCP_PACKET>*)pClient)->Connect() != 0)
	{
		printf("Can not link to %s:%d\n", ip, port);
		return;
	}
	pClient->BeforeNetworking();
	
	int nTimer;
	while(nTimes--)
	{
		nTimer = 100*M / (8*K);
		timeSpeed.SetMark();
		pBuf->idx = pClient->GetPacketPtr()->getIdx()++;
		while(nTimer --)
		{			
			pBuf->packetSize =sizeof(NETBUF);		//	8K
			memcpy(pClient->GetPacketPtr(), pBuf, sizeof(NETBUF));	
			pClient->GetPacketPtr()->size() = pBuf->packetSize;

			pClient->nSendLen = pClient->Send();
			if(pClient->nSendLen < 0) break;
			if(pClient->nSendLen == 0) {nTimer++; continue;} 

			if(nTimer % (10*M/(8*K)) == 0)
				printf("send : %d%%\n", 10 - nTimer / (10*M/(8*K)));
		
		#if RECV_AND_SEND		
			pClient->nRecvLen = pClient->Receive();
		#endif
		}
		if(nTimer > 0)
		{
			printf("send error\n");
			getchar();
			break;
		}
		speed = 100 / timeSpeed.GetSpeed();
		printf("\n%d Send to %s:%d %d MByte complete, speed: %fM/S\n", pBuf->idx, ip, port, 100, speed);
	}

	pClient->LaterNetworking();
	pClient->Close();
	
	delete pBuf;
	delete pClient;
}

int main(int argc, char const *argv[])
{
	if(argc == 3)
		TCP_Server(atoi(argv[1]), atoi(argv[2]));
	else if(argc == 4)
		TCP_Client((char*)argv[1], atoi(argv[2]), atoi(argv[3]));
	else MSG("args error\nServer : port\nClient : IP, port, times\n");	
	getchar();
	return 0;
}
